//! 特性管理协议

pub mod offline;

use crate::id::*;
use crate::link::Link;
use crate::net;
use crate::protocol;
use log::warn;

/// 协议ID
pub const PROTOCOL_ID: u8 = 2;
/// 特性ID
pub enum Feature {
    Offline = offline::FEATURE_ID as _,
    Unknow = 0xFE,
}
/// 操作码
#[derive(Clone, Copy)]
pub(crate) enum OpCode {
    Disable = 0x10,
    Enable = 0x11,
    Read = 0x20,
    ReadResult = 0x21,
    Operate = 0x31,
    Unknow = 0xFE,
}
impl From<u8> for OpCode {
    fn from(opcode: u8) -> Self {
        match opcode {
            x if x == OpCode::Disable as u8 => OpCode::Disable,
            x if x == OpCode::Enable as u8 => OpCode::Enable,
            x if x == OpCode::Read as u8 => OpCode::Read,
            x if x == OpCode::ReadResult as u8 => OpCode::ReadResult,
            x if x == OpCode::Operate as u8 => OpCode::Operate,
            _ => OpCode::Unknow,
        }
    }
}
/// 特性管理协议
fn when_recv(remote: &Id, data: &[u8]) {
    match data[0] {
        feature if (feature == Feature::Offline as u8) => {
            offline::when_recv(remote, data[1].into(), &data[2..]);
        }
        _ => {
            warn!("unknow feature.");
        }
    }
}

/// 初始化
pub fn init() {
    protocol::add_protocol(PROTOCOL_ID, when_recv);
}
pub fn enable(link: Link, feature: Feature) {
    let buf = [feature as u8, OpCode::Enable as u8];
    net::send(PROTOCOL_ID, &buf, &ID_ALL, Some(link));
}
pub fn disable(link: Link, feature: Feature) {
    let buf = [feature as u8, OpCode::Disable as u8];
    net::send(PROTOCOL_ID, &buf, &ID_ALL, Some(link));
}
pub fn read(link: Link, feature: Feature) {
    let buf = [feature as u8, OpCode::Read as u8];
    net::send(PROTOCOL_ID, &buf, &ID_ALL, Some(link));
}
